package com.changsideal.excel.util.excel;

import com.changsideal.excel.annotation.Column;
import com.changsideal.excel.annotation.Sheet;
import com.changsideal.excel.util.ExcelBasicTool;
import com.changsideal.exception.ExcelToolException;
import com.changsideal.tool.BasicTool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.springframework.stereotype.Component;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName BeanToExcelUtil
 * @Description Bean转Excel文件
 * @Author Create by Chansideal.Haosc
 * @Date 2019/7/9 13:19
 * @Version 1.0
 **/
@Slf4j
@Component
public class BeanToExcelUtil extends ExcelBasicTool implements IBeanToExcelOpear {

    public BeanToExcelUtil() {
        super();
    }

    private void createExcel(List conditionList, Class conditionClass) {
        if (BasicTool.checkOrNull(conditionList)
                || conditionList.size() == 0
                || BasicTool.checkOrNull(conditionClass)) {
            log.error("NULL EXCEPTION：需要生成的Excel对象为空");
            throw new ExcelToolException("NULL EXCEPTION：需要生成的Excel对象为空");
        }

        Field[] declaredFields = conditionClass.getDeclaredFields();
        List<Column> columns = new ArrayList<>(declaredFields.length);
        List<Field> fields = new ArrayList<>(declaredFields.length);
        for (Field declaredField : declaredFields) {
            Column annotation = declaredField.getAnnotation(Column.class);
            if (Modifier.isPrivate(declaredField.getModifiers())
                    && !Modifier.isStatic(declaredField.getModifiers()) && annotation.importFlag()) {
                columns.add(annotation);
                fields.add(declaredField);
            }
        }

        Sheet sheetAnno = (Sheet) conditionClass.getAnnotation(Sheet.class);
        if (BasicTool.checkOrNull(sheetAnno)) {
            log.error("NULL EXCEPTION：没有sheet元素");
            throw new ExcelToolException("NULL EXCEPTION：没有sheet元素");
        }
        org.apache.poi.ss.usermodel.Sheet mySheet;
        if (StringUtils.isBlank(sheetAnno.value())) {
            mySheet = workbook.createSheet();
        } else {
            mySheet = workbook.createSheet(sheetAnno.value().trim());
        }

        // 标题行
        Row row = mySheet.createRow(0);
        int[] widths = new int[columns.size()];
        CellStyle[] types = new CellStyle[columns.size()];
        for (int i = 0; i < columns.size(); i++) {
            CellStyle columuStyle = workbook.createCellStyle();
            columuStyle.setAlignment(columns.get(i).alignStyle());
            types[i] = columuStyle;

            CellStyle headStyle = workbook.createCellStyle();
            headStyle.setFillBackgroundColor(sheetAnno.headBackGround().getIndex());
            headStyle.setAlignment(columns.get(i).alignStyle());
            widths[i] = columns.get(i).width();

            Cell cell = row.createCell(i, CellType.STRING);
            cell.setCellStyle(headStyle);
            cell.setCellValue(columns.get(i).value());
        }

        for (int i = 0; i < conditionList.size(); i++) {
            int rowIndex = i + 1;
            Object obj = conditionList.get(i);
            Row columnRow = mySheet.createRow(rowIndex);
            for (Field field : fields) {
                try {
                    field.setAccessible(true);
                    String finalString = BasicTool.invocationString(field.get(obj));
                    Cell eachColumn = columnRow.createCell(i, CellType.STRING);
                    eachColumn.setCellValue(finalString);
                    eachColumn.setCellStyle(types[i]);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

        for (int i = 0; i < fields.size(); i++) {
            int fieldWidth = widths[i];
            if (fieldWidth > 0) {
                mySheet.setColumnWidth(i, fieldWidth);
            } else {
                mySheet.autoSizeColumn((short) i);
            }
        }
    }

    @Override
    public void exportFile(List processList, Class aClass, String saveFilePath) {
        createExcel(processList, aClass);
        try (FileOutputStream outputStream = new FileOutputStream(saveFilePath)) {
            workbook.write(outputStream);
            outputStream.flush();
            log.info("文件名：" + saveFilePath + "导出完成！");
        } catch (IOException e) {
            log.error(e.getMessage());
            throw new ExcelToolException(e.getMessage());
        }
    }

    @Override
    public byte[] exportBytes(List processList, Class aClass, String saveFilePath) {
        createExcel(processList, aClass);
        int size = 1024;
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(size)) {
            workbook.write(outputStream);
            outputStream.flush();
            return outputStream.toByteArray();
        } catch (IOException e) {
            log.error(e.getMessage());
            throw new ExcelToolException(e.getMessage());
        }
    }
}
